package com.example.backetballgame.gui;


import com.example.backetballgame.event.EventBus;
import com.example.backetballgame.event.EventListener;
import com.example.backetballgame.event.FrameEvent;
import com.example.backetballgame.player.Player;
import com.example.backetballgame.store.StoreManage;

import javax.swing.*;


import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

/**
 * A frame for the battle preparation interface.
 * Users can select a maximum of 5 athletes from the athlete gallery to participate in the game,
 * and can also go to the athlete store to purchase or sell athletes.
 * Once the athlete selection is completed, users can enter the next interface to select opponents.
 */
public class BattlePreparationFrame extends JFrame implements EventListener {

    private static final int MAX_SELECTED_ATHLETES = 5; // Maximum number of selected athletes
    private final JLabel currentSeasonLabel;

    private String teamName; // Team name
    private int season; // Season
    private List<Player> chosePlayers = new ArrayList<>();// List of selected athletes

    // Athlete gallery
    private JPanel athleteGallery;

    // Existing amount label
    private JLabel moneyLabel;

    // Prompt label
    private JLabel infoLabel;

    /**
     * Creates a new BattlePreparationFrame object.
     * Initializes the athlete selection status, and sets the layout and components of the interface.
     */
    public BattlePreparationFrame() {
        // Get the team name and season information from the previous interface
        teamName = StoreManage.getTeamName();
        season = StoreManage.getSeason();

        // Initialize athlete selection status
        chosePlayers.clear();

        // Set the interface layout
        setLayout(new BorderLayout());

        // Create the top panel
        JPanel topPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
        topPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        JLabel teamLabel = new JLabel("Team Name: " + teamName);
        teamLabel.setFont(new Font("Arial", Font.BOLD, 20));
        topPane.add(teamLabel);

        JLabel seasonLabel = new JLabel("Season duration: " + season + " weeks");
        seasonLabel.setFont(new Font("Arial", Font.BOLD, 20));
        topPane.add(seasonLabel);

        currentSeasonLabel = new JLabel("Currently: " + StoreManage.getCurrentSeason() + " weeks");
        currentSeasonLabel.setFont(new Font("Arial", Font.BOLD, 20));
        topPane.add(currentSeasonLabel);
        add(topPane, BorderLayout.NORTH);

        // Create the center panel
        JPanel centerPane = new JPanel(new BorderLayout());
        centerPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // Create the existing amount label
        moneyLabel = new JLabel("Existing amount: " + StoreManage.getTotalMonty() + " yuan");
        moneyLabel.setFont(new Font("Arial", Font.PLAIN, 20));
        centerPane.add(moneyLabel, BorderLayout.NORTH);

        // Create the athlete gallery control
        athleteGallery = new JPanel(new GridLayout(0, 3, 10, 10));
        updateAthleteGallery();
        JScrollPane galleryScrollPane = new JScrollPane(athleteGallery);
        galleryScrollPane.setPreferredSize(new Dimension(0, 300));
        centerPane.add(galleryScrollPane, BorderLayout.CENTER);

        // Create the prompt label
        infoLabel = new JLabel("Please select no more than " + MAX_SELECTED_ATHLETES + " athletes");
        infoLabel.setFont(new Font("Arial", Font.PLAIN, 16));
        centerPane.add(infoLabel, BorderLayout.SOUTH);

        add(centerPane, BorderLayout.CENTER);

        // Create the button panel
        JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 20));
        buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // Create the athlete store button
        JButton shopButton = new JButton("Athlete Store");
        shopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new PlayerShopFrame(BattlePreparationFrame.this);
            }
        });
        buttonPane.add(shopButton);


        // Create the return button
        JButton backButton = new JButton("Return");
        backButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO: Return to the previous interface
            }
        });
        buttonPane.add(backButton);

        // Create the continue button
        JButton continueButton = new JButton("Continue");
        continueButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO: Enter the next interface
                if (chosePlayers.size() != MAX_SELECTED_ATHLETES) {
                    JOptionPane.showMessageDialog(null, "Please select " + MAX_SELECTED_ATHLETES + " athletes to participate!");
                } else if (chosePlayers.stream().anyMatch(it -> it.getFatigue() == 100)) {
                    JOptionPane.showMessageDialog(null, "Some team members are too tired, substitute them for a rest!");
                } else {
                    StoreManage.saveActivePlayers(chosePlayers);
                    SelectOpponentFrame selectOpponentFrame = new SelectOpponentFrame();
                    selectOpponentFrame.setVisible(true);
                }
            }
        });
        buttonPane.add(continueButton);

        JButton nextWeekButton = new JButton("Next week");
        nextWeekButton.addActionListener(event -> {
            if (StoreManage.isLastWeek()) {
                dispose();
                SeasonEndFrame seasonEndFrame = new SeasonEndFrame();
                seasonEndFrame.setVisible(true);
            }else{
                StoreManage.nextWeek();
                JOptionPane.showMessageDialog(null, "Enter the next week");
            }
        });

        buttonPane.add(nextWeekButton);


        add(buttonPane, BorderLayout.SOUTH);

        // Set the window properties
        setTitle("Athletes");
        setSize(800, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        EventBus.getInstance().subscribe(this);
    }

    /**
     * Update the display of the athlete gallery control.
     */
    private void updateAthleteGallery() {
        athleteGallery.removeAll();

        List<Player> allPlayers = StoreManage.getPlayers();
        for (int i = 0; i < allPlayers.size(); i++) {
            Player itemPlayer = allPlayers.get(i);

            JPanel athletePanel = new JPanel(new BorderLayout());
            athletePanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

            JPanel infoPanel = new JPanel(new GridLayout(4, 1));

            JLabel nameLabel = new JLabel(itemPlayer.getName());
            nameLabel.setFont(new Font("Arial", Font.PLAIN, 16));

            JLabel strengthLabel = new JLabel("Strength: " + itemPlayer.getStrength());
            strengthLabel.setFont(new Font("Arial", Font.PLAIN, 14));

            JLabel defenseLabel = new JLabel("Defense: " + itemPlayer.getDefense());
            defenseLabel.setFont(new Font("Arial", Font.PLAIN, 14));

            JLabel fatigueLabel = new JLabel("Fatigue: " + itemPlayer.getFatigue());
            fatigueLabel.setFont(new Font("Arial", Font.PLAIN, 14));

            infoPanel.add(nameLabel);
            infoPanel.add(strengthLabel);
            infoPanel.add(defenseLabel);
            infoPanel.add(fatigueLabel);

            JButton selectButton = new JButton(chosePlayers.contains(itemPlayer) ? "Cancel selection" : "Select");

            final int k = i;
            selectButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (chosePlayers.contains(itemPlayer)) {
                        chosePlayers.remove(itemPlayer);
                        updateInfoLabel();
                        updateAthleteGallery();
                    } else if (chosePlayers.size() < MAX_SELECTED_ATHLETES) {
                        chosePlayers.add(itemPlayer);
                        updateInfoLabel();
                        updateAthleteGallery();
                    }
                }
            });
            athletePanel.add(infoPanel, BorderLayout.CENTER);
            athletePanel.add(selectButton, BorderLayout.EAST);
            athletePanel.setPreferredSize(new Dimension(100, 100));
            athleteGallery.add(athletePanel);
        }
        athleteGallery.revalidate();
        athleteGallery.repaint();
    }

    /**
     * Update the display of the existing amount label.
     */
    private void updateMoneyLabel() {
        moneyLabel.setText("Existing amount: " + StoreManage.getTotalMonty() + " ¥");
    }

    /**
     * Update the display of the prompt label.
     */
    private void updateInfoLabel() {
        switch (chosePlayers.size()) {
            case 0:
                infoLabel.setText("Please select no more than " + MAX_SELECTED_ATHLETES + " athletes");
                break;
            case MAX_SELECTED_ATHLETES:
                infoLabel.setText("Selected " + MAX_SELECTED_ATHLETES + " athletes, cannot select more");
                break;
            default:
                infoLabel.setText("Selected " + chosePlayers.size() + " athletes, can select " + (MAX_SELECTED_ATHLETES - chosePlayers.size()) + " more");
                break;
        }
    }

    /**
     * Refreshes the interface by updating the athlete gallery, existing amount label and prompt label.
     */
    public void refresh() {
        updateCurrentSeasonLabel();
        updateAthleteGallery();
        updateMoneyLabel();
        updateInfoLabel();
    }

    /**
     * Updates the display of the current season label.
     */
    private void updateCurrentSeasonLabel() {
        currentSeasonLabel.setText("Currently: " + StoreManage.getCurrentSeason() + " weeks");
    }

    /**
     * Unsubscribes the instance from the event bus before disposing of the frame.
     */
    @Override
    public void dispose() {
        EventBus.getInstance().unsubscribe(this);
        super.dispose();
    }

    /**
     * The main method that creates a new BattlePreparationFrame object to start the interface.
     * @param args The command line arguments.
     */
    public static void main(String[] args) {
        new BattlePreparationFrame();
    }

    /**
     * Receives events from the event bus and performs corresponding actions.
     * @param frameEvent The event received.
     */
    @Override
    public void onEventReceived(FrameEvent frameEvent) {
        switch (frameEvent.getEventType()) {
            case 1:
                // Refresh the data
                refresh();
                break;
            default:
                break;
        }
    }
}